/**
 *******************************************************************************
 * @brief       Provide a brief description of the module here (Single line).
 * 
 * @author      Ashwin
 * 
 * @file        hd44780.h
 * 
 * @version
 * 
 * @date        Feb 1, 2012 10:29:26 PM
 * 
 * @details     Provide a detailed description of the module here (Multi-line).
 * 
 * @pre         Mention any preconditions required to use this module.
 * 
 * @bug         List any bugs in this module.
 * 
 * @note        List any odd modes while using this module.
 * 
 * @warning     List any warnings against using the objects of this module.
 *******************************************************************************
 * @copyright 2012
 * <a href="http://www.afflatustech.com">Afflatus Techtronics</a>
 * and <a href="http://www.ashwinvijayakumar.co.nr">Ashwin Vijayakumar</a>
 * @n@n
 * This work is licensed under the Creative Commons
 * Attribution-NonCommercial-ShareAlike 3.0 Unported License. To view a copy
 * of this license, visit http://creativecommons.org/licenses/by-nc-sa/3.0/ or
 * send a letter to Creative Commons, 444 Castro Street, Suite 900, Mountain
 * View, California, 94041, USA.
 *******************************************************************************
 */

/**@cond Include guard symbol - Protect against multiple inclusions  @endcond */

#ifndef HD44780_H_
#define HD44780_H_

/**@cond ***********************************************************************
 * Add #include "hd44780.h" in source files that need access to the below 
 * listed declarations.
 ******************************************************************* @endcond */

/**@cond -----------------------------------------------------------------------
 * Includes section
 * Add all #include here.
 * ----------------------------------------------------------------- @endcond */

/**@cond System headers -------------------------------------------- @endcond */

/**@cond Local headers --------------------------------------------- @endcond */
#include "Std_Types.h"
#include "Platform_Types.h"
#include "MCU_Conf.h"
#include "Gpio_Driver.h"
#include "Hd44780_Fonts.h"

/**@cond -----------------------------------------------------------------------
 * typedef section (Project scope)
 * Add typedef's with project scope here.
 * Capitalization: Upper_Camel_Case.
 * ----------------------------------------------------------------- @endcond */

/**
 * @brief HD44780 Byte Type.
 * @details This type shall be used to distinguish between Instruction and Data.
 */
typedef enum
{
  HD44780_INS           = 0,    /**< HD44780 Instruction. */
  HD44780_DAT           = 1     /**< HD44780 Data. */
} Hd44780_ByteType;

/**
 * @brief HD44780 Configuration Type.
 * @details This type shall be used to declare a variable which will hold the
 * configuration parameters for HD44780 initialization.
 * @warning DO NOT CHANGE THE SIZE OR ORDER OF THIS STRUCTURE
 * Refer Hd44780_Init() before making any changes to this structure.
 */
typedef union
{
  uint8_t byte;
  struct
  {
    uint8_t shift       :1;     /**< Entry Mode Set, S: Shift display. */
    uint8_t increment   :1;     /**< Entry Mode Set, I/D: Increment/Decrement cursor position. */
    uint8_t blink       :1;     /**< Display On/Off Control, B: Blink cursor. */
    uint8_t cursor      :1;     /**< Display On/Off Control, C: Show cursor. */
    uint8_t font        :1;     /**< Function Set, F: Font. */
    uint8_t lines       :1;     /**< Function Set, N: Number of display line. */
    uint8_t reserved    :2;     /**< Reserved for future use. */
  } bit;
} Hd44780_ConfigType;

/**@cond -----------------------------------------------------------------------
 * Constants section (Project scope)
 * Add all constants with project scope here.
 * Capitalization: ALL_CAPS.
 * ----------------------------------------------------------------- @endcond */

/* Comment below line LCD should use s/w delay instead of checking the Busy Flag */
#define HD44780_RW_PIN_EN

#define HD44780_DATA_DIR                TRISD
#define HD44780_CTRL_DIR                TRISD

#define HD44780_DATA_PORT               PORTD
#define HD44780_CTRL_PORT               PORTD
#define HD44780_RS                      PIN1
#define HD44780_EN                      PIN3
#ifdef HD44780_RW_PIN_EN
#define HD44780_RW                      PIN2
#define HD44780_CTRL_PORT_MSK           (HD44780_RS | HD44780_RW | HD44780_EN)
#else /* (HD44780_RW_PIN_EN) */
#define HD44780_CTRL_PORT_MSK           (HD44780_RS | HD44780_EN)
#endif

#define HD44780_BF_CHECK_TIMEOUT        10

/*  */
#define HD44780_DATA_LEN                4

/* Goes hand-in-hand with GPIO_WIDTH (Gpio_Driver.h) */
/**
 * @pre Update GPIO_WIDTH in Gpio_Driver.h
 */
#define HD44780_DATA_POSITION           4

#if(4 == HD44780_DATA_LEN)

#if((GPIO_WIDTH < 16) && (HD44780_DATA_POSITION >= 8) || (GPIO_WIDTH < 32) && (HD44780_DATA_POSITION >= 16))
#error "HD44780_DATA_PORT_MSK is out of GPIO scope. Please update GPIO_WIDTH in Gpio_Driver.h"
#else
#if(0 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN3 | PIN2 | PIN1 | PIN0)
#elif(4 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN7 | PIN6 | PIN5 | PIN4)
#elif(8 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN11 | PIN10 | PIN9 | PIN8)
#elif(12 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN15 | PIN14 | PIN13 | PIN12)
#elif(16 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN19 | PIN18 | PIN17 | PIN16)
#elif(20 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN23 | PIN22 | PIN21 | PIN20)
#elif(24 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN27 | PIN26 | PIN25 | PIN24)
#elif(28 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN31 | PIN30 | PIN29 | PIN28)
#endif /* (0 == HD44780_DATA_POSITION) */
#endif /* ((GPIO_TYPE < 16) && ...) */

#elif(8 == HD44780_DATA_LEN)

#if((GPIO_WIDTH < 16) && (HD44780_DATA_POSITION >= 4) || (GPIO_WIDTH < 32) && (HD44780_DATA_POSITION >= 12))
#error "HD44780_DATA_PORT_MSK is out of GPIO scope. Please update GPIO_WIDTH in Gpio_Driver.h"
#else
#if(0 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN7 | PIN6 | PIN5 | PIN4 | PIN3 | PIN2 | PIN1 | PIN0)
#elif(4 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN11 | PIN10 | PIN9 | PIN8 | PIN7 | PIN6 | PIN5 | PIN4)
#elif(8 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN15 | PIN14 | PIN13 | PIN12 | PIN11 | PIN10 | PIN9 | PIN8)
#elif(12 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN19 | PIN18 | PIN17 | PIN16 | PIN15 | PIN14 | PIN13 | PIN12)
#elif(16 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN23 | PIN22 | PIN21 | PIN20 | PIN19 | PIN18 | PIN17 | PIN16)
#elif(20 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN27 | PIN26 | PIN25 | PIN24 | PIN23 | PIN22 | PIN21 | PIN20)
#elif(24 == HD44780_DATA_POSITION)
#define HD44780_DATA_PORT_MSK   (PIN31 | PIN30 | PIN29 | PIN28 | PIN27 | PIN26 | PIN25 | PIN24)
#endif /* (0 == HD44780_DATA_POSITION) */
#endif /* ((GPIO_TYPE < 16) && ...) */

#endif /* (4 == HD44780_DATA_LEN) */

#define HD44780_NO_OF_ROWS      2
#define HD44780_NO_OF_COLUMNS   16

#if(8 == HD44780_NO_OF_COLUMNS)
#define HD44780_ROW0_FIRST_COLUMN       0x00
#define HD44780_ROW0_LAST_COLUMN        0x07
#define HD44780_ROW1_FIRST_COLUMN       0x40
#define HD44780_ROW1_LAST_COLUMN        0x47
#define HD44780_LAST_DDRAM_ADDR         0x47
#if(4 == HD44780_NO_OF_ROWS)
#define HD44780_ROW2_FIRST_COLUMN       0x14
#define HD44780_ROW2_LAST_COLUMN        0x1B
#define HD44780_ROW3_FIRST_COLUMN       0x54
#define HD44780_ROW3_LAST_COLUMN        0x5B
#define HD44780_LAST_DDRAM_ADDR         0x5B
#endif /* [(4 == HD44780_NO_OF_ROWS)] */
#elif(16 == HD44780_NO_OF_COLUMNS)
#define HD44780_ROW0_FIRST_COLUMN       0x00
#define HD44780_ROW0_LAST_COLUMN        0x0F
#define HD44780_ROW1_FIRST_COLUMN       0x40
#define HD44780_ROW1_LAST_COLUMN        0x4F
#define HD44780_LAST_DDRAM_ADDR         0x4F
#if(4 == HD44780_NO_OF_ROWS)
#define HD44780_ROW2_FIRST_COLUMN       0x14
#define HD44780_ROW2_LAST_COLUMN        0x23
#define HD44780_ROW3_FIRST_COLUMN       0x54
#define HD44780_ROW3_LAST_COLUMN        0x63
#define HD44780_LAST_DDRAM_ADDR         0x63
#endif /* [(4 == HD44780_NO_OF_ROWS)] */
#elif(20 == HD44780_NO_OF_COLUMNS)
#define HD44780_ROW0_FIRST_COLUMN       0x00
#define HD44780_ROW0_LAST_COLUMN        0x13
#define HD44780_ROW1_FIRST_COLUMN       0x40
#define HD44780_ROW1_LAST_COLUMN        0x53
#define HD44780_LAST_DDRAM_ADDR         0x53
#if(4 == HD44780_NO_OF_ROWS)
#define HD44780_ROW2_FIRST_COLUMN       0x14
#define HD44780_ROW2_LAST_COLUMN        0x27
#define HD44780_ROW3_FIRST_COLUMN       0x54
#define HD44780_ROW3_LAST_COLUMN        0x67
#define HD44780_LAST_DDRAM_ADDR         0x67
#endif /* [(4 == HD44780_NO_OF_ROWS)] */
#endif /* [(8 == HD44780_NO_OF_COLUMNS)] */

#define HD44780_DECREMENT       0
#define HD44780_INCREMENT       1

#define HD44780_SHIFT_DISABLE   0
#define HD44780_SHIFT_ENABLE    1

#define HD44780_DISPLAY_OFF     0
#define HD44780_DISPLAY_ON      1

#define HD44780_CURSOR_OFF      0
#define HD44780_CURSOR_ON       1

#define HD44780_BLINK_OFF       0
#define HD44780_BLINK_ON        1

#define HD44780_ONE_LINE        0
#define HD44780_TWO_LINE        1

#define HD44780_5x8_FONT        0
#define HD44780_5x10_FONT       1

#if(HD44780_NO_OF_ROWS > 0)
#define HD44780_LINE0           0
#endif
#if(HD44780_NO_OF_ROWS > 1)
#define HD44780_LINE1           1
#endif
#if(HD44780_NO_OF_ROWS > 2)
#define HD44780_LINE2           2
#endif
#if(HD44780_NO_OF_ROWS > 3)
#define HD44780_LINE3           3
#endif

/**@cond -----------------------------------------------------------------------
 * Macros section (Project scope)
 * Add all macros with project scope here.
 * Capitalization: ALL_CAPS.
 * ----------------------------------------------------------------- @endcond */

#define Hd44780_Putc(character)                         \
    do                                                  \
    {                                                   \
        is_Hd44780_Busy(HD44780_BF_CHECK_TIMEOUT);      \
        Hd44780_ByteWrite(character, HD44780_DAT);      \
    } while(0);

#define Hd44780_ClearDisplay(void)                      \
    do                                                  \
    {                                                   \
        is_Hd44780_Busy(HD44780_BF_CHECK_TIMEOUT);      \
        Hd44780_ByteWrite(0x01, HD44780_INS);           \
    } while(0);

#define Hd44780_getc()          Hd44780_ByteRead(HD44780_DAT)

/**@cond -----------------------------------------------------------------------
 * Global variables section (Project scope)
 * Add global variables with project scope here. 
 * Capitalization: lower_case.
 * Declare them with 'extern' keyword.
 * ----------------------------------------------------------------- @endcond */

/**@cond -----------------------------------------------------------------------
 * Function prototypes section (Project scope)
 * Add prototypes for all functions with project scope here. 
 * Capitalization: lower_Camel_Case.
 * ----------------------------------------------------------------- @endcond */

Std_ReturnType Hd44780_Init(Hd44780_ConfigType* ConfigPtr);

Std_ReturnType Hd44780_Reconfig(Hd44780_ConfigType* ConfigPtr, Std_BoolType clear_display);

Std_BoolType is_Hd44780_Busy(uint8_t time_out);

Std_ReturnType Hd44780_ByteWrite(uint8_t byt, Hd44780_ByteType bytType);

uint8_t Hd44780_ByteRead(Hd44780_ByteType bytType);

Std_ReturnType Hd44780_GoToXY(uint8_t row, uint8_t column);

Std_ReturnType Hd44780_GetXY(uint8_t *X, uint8_t *Y);

uint8_t Hd44780_WriteLine(uint8_t *S, uint8_t len, uint8_t line_no);

uint8_t Hd44780_puts(uint8_t *S);

Std_ReturnType Hd44780_LoadCGRAM(Hd44780_FontPlotType *font_ptr, uint8_t cgram_addr);

Std_ReturnType Hd44780_LoadCustomFont(Hd44780_FontPlotType *font_ptr, uint8_t len);

Std_ReturnType Hd44780_15x16_putc(Hd44780_FontIndexType *font_index, uint8_t character);

/**@cond -----------------------------------------------------------------------
 * Getter/setter prototype section (Project scope)
 * Add prototypes for getter/setter methods here.
 * Capitalization: get_Camel_Case/is_Camel_Case/set_Camel_Case. 
 * ----------------------------------------------------------------- @endcond */


#endif /* Hd44780_H_ */


/** END OF FILE ********************* Copyright (C) 2012 Afflatus Techtronics */
